/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frzlib.c                                           */
/*  NOTE      =                                                    */
/*  DATE      = 2015/06/16 by songbb                               */
/*******************************************************************/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
#include <fcntl.h>
#include <stdio.h>

#include "frmem.h"
#include "frcomm.h"
#define GZIP_DEFAULT_MALLOC  1024

int frzlib_inflater(Byte *p_zdata, uLong u_l_nzdata,
                      char **pp_data, uLong *p_ndata)
{
    int i_err = 0;
    int i_tmp_len = 0, i_tmp_all = 0;
    z_stream st_stream = {0}; /* decompression stream */
    char *p_data = NULL, *p_tmp = NULL;
    int i_malloc = GZIP_DEFAULT_MALLOC, i_use = 0;

    //所有的数据
    p_data = (char *)frmalloc(i_malloc);
    if (p_data == NULL)
        return FR_FAIL;
    
    //临时的解压的数据
    p_tmp = (char *)frmalloc(GZIP_DEFAULT_MALLOC);
    if (p_tmp == NULL)
        goto err;
        
    st_stream.zalloc = (alloc_func)0;
    st_stream.zfree = (free_func)0;
    st_stream.opaque = (voidpf)0;
    st_stream.next_in = p_zdata;
    st_stream.avail_in = u_l_nzdata;
    
    if(inflateInit(&st_stream) != Z_OK)
        goto err;
        
    do
    {
        st_stream.avail_out = GZIP_DEFAULT_MALLOC;
        st_stream.next_out = (Byte *)p_tmp;
        
        i_err = inflate(&st_stream, Z_NO_FLUSH);
        if (i_err < 0)
            goto err;
        
        //已经解码成功的长度
        i_tmp_len = GZIP_DEFAULT_MALLOC - st_stream.avail_out;
        i_tmp_all += i_tmp_len;
        if (i_tmp_all >= i_malloc)
        {
            char *p_remalloc = NULL;
            //remalloc
            p_remalloc = (char *) frmalloc(i_tmp_all + 1024);
            if (p_remalloc == NULL)
                goto err;
            
            memcpy(p_remalloc, p_data, i_malloc);
            i_malloc = i_tmp_all + 1024;
            
            frfree(p_data);
            p_data = p_remalloc;
        }
        memcpy(p_data + i_use, p_tmp, i_tmp_len);
        i_use += i_tmp_len;
        
    } while(0 == st_stream.avail_out);

    *p_ndata = i_tmp_all;
    p_data[i_tmp_all] = '\0';
    *pp_data = p_data;
    frfree(p_tmp);
    inflateEnd(&st_stream);
    
    return FR_SUCC;
err:
    if (p_data)
        frfree(p_data);
    if (p_tmp)
        frfree(p_tmp);
    inflateEnd(&st_stream);
    return FR_FAIL;
}
